package com.hyacinth.cloudnote.common.exception.handler;


import com.hyacinth.cloudnote.common.security.SecurityLog;
import com.hyacinth.cloudnote.common.utils.HttpUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

/**
 * 特殊异常定制处理，打印404等系统异常日志，提升安全控制能力。<br>
 * 参考: ErrorMvcAutoConfiguration, BasicErrorController, AbstractErrorController。
 */
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
@ApiIgnore
public class CustomErrorController extends BasicErrorController {

    @Autowired
    public CustomErrorController(final ErrorAttributes errorAttributes,
                                 final ServerProperties serverProperties, final ObjectProvider<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, serverProperties.getError(), errorViewResolvers.orderedStream()
                .collect(Collectors.toList()));
    }

    @Override
    protected HttpStatus getStatus(final HttpServletRequest request) {
        final HttpStatus status = super.getStatus(request);

        final String clientIp = HttpUtils.getClientIP(request);
        // 参考DefaultErrorAttributes中的实现
        final String requestURI = (String) (request.getAttribute("javax.servlet.error.request_uri"));

        if ((status == HttpStatus.NOT_FOUND) || (status == HttpStatus.METHOD_NOT_ALLOWED)) {
            SecurityLog.pageNotFound.warn("[{}]请求URI不存在: {} {}", clientIp, request.getMethod(), requestURI);
        } else if ((status == HttpStatus.FORBIDDEN) || (status == HttpStatus.PAYMENT_REQUIRED)) {
            SecurityLog.unauthorized.warn("[{}]请求URI被禁止: {} {}", clientIp, request.getMethod(), requestURI);
        } else if (status == HttpStatus.UNAUTHORIZED) {
            SecurityLog.unauthorized.warn("[{}]请求URI未授权: {} {}", clientIp, request.getMethod(), requestURI);
        }
        return status;
    }
}
